/*!
\copyright  Copyright (c) 2023 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\brief      USB dongle HID interface

*/

#include "usb_dongle_hid.h"
#include "usb_hid_datalink.h"
#include "usb_dongle_logging.h"
#include "ui.h"

#ifdef INCLUDE_SOURCE_APP_LE_AUDIO
#include "usb_dongle_lea.h"
#include "usb_app_source_le_audio.h"
#include "le_audio_client.h"
#endif /* INCLUDE_SOURCE_APP_LE_AUDIO */

/*! \brief Configure command header data length */
#define USB_DONGLE_REPORT_DATA_HEADER_LEN   (3)

/*! \brief Length of data for USB_LEA_HID_CMD_SWITCH_LEA_MODE command */
#define USB_DONGLE_LEA_MODE_CMD_DATA_LEN    (1)

/*! \brief USB HID Command types */
typedef enum
{
    /*! Command for setting broadcast source name */
    USB_LEA_HID_CMD_SET_LEA_BROADCAST_NAME,

    /*! Command for setting broadcast code */
    USB_LEA_HID_CMD_SET_LEA_BROADCAST_CODE,

    /*! Command for switching the mode */
    USB_LEA_HID_CMD_SWITCH_LEA_MODE,
} usb_hid_command_t;

/*! \brief Types of modes supported for USB_LEA_HID_CMD_SWITCH_LEA_MODE command */
typedef enum
{
    /*! Reserved for future */
    USB_SET_LEA_MODE_RESERVED,

    /*! To set the mode to unicast */
    USB_SET_LEA_MODE_UNICAST,

    /*! Command for setting the broadcast to public broadcast */
    USB_SET_LEA_MODE_BCAST_PBP,

    /*! Command for setting the broadcast to TMAP broadcast */
    USB_SET_LEA_MODE_BCAST_TMAP
} usb_hid_set_lea_modes_t;

typedef struct
{
    /*! Report ID of the received HID report */
    uint8 report_id;

    /*! Configure command. See usb_hid_command_t */
    uint8 cmd;

    /*! Length of the command data */
    uint8 len;
} usb_lea_hid_command_data_t;

static void usbDongleHid_HandleHidReports(uint8 report_id, const uint8 *data, uint16 size)
{
#ifdef INCLUDE_SOURCE_APP_LE_AUDIO
    const usb_lea_hid_command_data_t *hid_hdr = (const usb_lea_hid_command_data_t *)data;
    /* Command data is after the first three bytes (ie, report id, cmd and len)  */
    const uint8 *hid_data = &data[USB_DONGLE_REPORT_DATA_HEADER_LEN];

    if (report_id != HID_REPORTID_CONFIGURE_CMD ||
        data == NULL || hid_hdr->len > size - USB_DONGLE_REPORT_DATA_HEADER_LEN)
    {
        /* Ignore if the data received is not valid or report ID does not match */
        return;
    }

    switch (hid_hdr->cmd)
    {
        case USB_LEA_HID_CMD_SET_LEA_BROADCAST_NAME:
        {
            DEBUG_LOG_FN_ENTRY("usbDongleHid_HandleHidReports set bcast name");

            UsbDongle_SetLeaBroadcastSourceName((const char*)hid_data, hid_hdr->len);
        }
        break;

        case USB_LEA_HID_CMD_SET_LEA_BROADCAST_CODE:
        {
            DEBUG_LOG_FN_ENTRY("usbDongleHid_HandleHidReports set bacast code");

            UsbDongle_SetLeaBroadcastCode(hid_hdr->len != 0 ? hid_data : NULL);
        }
        break;

        case USB_LEA_HID_CMD_SWITCH_LEA_MODE:
        {
            if (hid_hdr->len == USB_DONGLE_LEA_MODE_CMD_DATA_LEN)
            {
                bool toggle = FALSE;

                if (hid_data[0] == USB_SET_LEA_MODE_UNICAST)
                {
                    toggle = UsbDongle_IsInLeaBroadcastMode();
                }
                else if (hid_data[0] == USB_SET_LEA_MODE_BCAST_PBP)
                {
                    toggle = !UsbDongle_IsInLeaBroadcastMode();
                    LeAudioClientBroadcast_SetPbpMode(TRUE);
                }
                else if (hid_data[0] == USB_SET_LEA_MODE_BCAST_TMAP)
                {
                    toggle = !UsbDongle_IsInLeaBroadcastMode();
                    LeAudioClientBroadcast_SetPbpMode(FALSE);
                }

                DEBUG_LOG_FN_ENTRY("usbDongleHid_HandleHidReports switch mode %d, toggle: %d",
                                    hid_data[0], toggle);

                if (toggle)
                {
                    Ui_InjectUiInput(ui_input_broadcast_mode_toggle);
                }
            }
        }
        break;

        default:
            DEBUG_LOG_ALWAYS("usbDongleHid_HandleHidReports unexpected command 0x%x", hid_hdr->cmd);
            Panic();
    }
#else
    UNUSED(report_id);
    UNUSED(data);
    UNUSED(size);
#endif /* INCLUDE_SOURCE_APP_LE_AUDIO */

}


bool UsbDongleHid_Init(Task task)
{
    DEBUG_LOG_FN_ENTRY("UsbDongleHid_Init");

    /* Register to receive report data from host via USB HID Datalink class */
    UsbHid_Datalink_RegisterHandler(usbDongleHid_HandleHidReports);

    UNUSED(task);

    return TRUE;
}
